#include "LoadXML.h"

#include <iostream>
#include <fstream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

void LoadXML::loadXML(string fileName) {
	doc = TiXmlDocument(fileName.c_str());

	bool ok = doc.LoadFile();
	if(!ok) {
		cout << "Erro a abrir o ficheiro XML!" << endl;
	}			
	
	this->no = doc.RootElement();
	TiXmlElement* dsx = doc.FirstChildElement("dsx");
	if(dsx == NULL) {
		cout << "Erro dsx!" << endl;
	}

	TiXmlElement *cenola = doc.RootElement()->FirstChildElement("scene");
	string nome = cenola->Attribute("root");
	int tamanho;
	cenola->QueryIntAttribute("axis_length", &tamanho);
	Cena *c = new Cena(nome,tamanho);
	setCena(c);
}

bool LoadXML::loadCena() {
	// cout << "AQQUIII: " << endl;
	// this->textElemento = no->FirstChildElement("textures");
	// this->matElemento = no->FirstChildElement("materials");
	// this->transElemento = no->FirstChildElement("transformations");
	// this->luzElemento = no->FirstChildElement("lights");
	// this->ilElemento = no->FirstChildElement("illumination");
	// this->vistElemento = no->FirstChildElement("views");

	
	if (textElemento == NULL) {
		cout << "Texturas nao encontradas\n";
		return false;
	} else if(matElemento == NULL) {
		cout << "Materiais nao encontrados\n";
		return false;
	} else if(transElemento == NULL) {
		cout << "Transformacoes nao encontradas\n";
		return false;
	}  else if(luzElemento == NULL) {
		cout << "Luzes nao encontradas\n";
		return false;
	} else if(ilElemento == NULL) {
		cout << "Iluminacao nao encontrada\n";
		return false;
	} else if(vistElemento == NULL) {
		cout << "Vistas nao encontradas\n";
		return false;
	}
	else {
		loadMateriais();
		this->leMapMateriais();
		loadTexturas();
		this->leMapTexturas();
		loadTransformacoes();
		this->leMapTransformacoes();
		loadLuzes();
		this->leMapLuzes();
		loadIluminacao();
		this->leMapIluminacao();
		loadVistas();
		this->leMapVistas();
		loadPrimitivas();
		this->leMapPrimitivas();
		loadComponentes();
		this->leMapComponentes();
		return true;
	}

}

bool LoadXML::loadMateriais() {

	TiXmlElement *mm = doc.RootElement()->FirstChildElement("materials");
	cout << "MATERIAIS" << endl;
	for(TiXmlElement *material(mm->FirstChildElement()); material != NULL; material = material->NextSiblingElement()) {
	
		if(material->ValueTStr() == "material") {
			string id_material = material->Attribute("id");
			if(id_material != "inherit") {


				for(TiXmlElement* propriedade(material->FirstChildElement()); propriedade != NULL; propriedade = propriedade->NextSiblingElement()) {
				
					Materiais *mat = new Materiais(id_material);
					float r,g,b,a,valor;
					// cout << "mm: " << id_material << endl;
					if(propriedade->ValueTStr() == "emission") {
						// cout << "emissao " << endl;
						propriedade->QueryFloatAttribute("r",&r);
						propriedade->QueryFloatAttribute("g",&g);
						propriedade->QueryFloatAttribute("b",&b);
						propriedade->QueryFloatAttribute("a",&a);
						mat->setEmissao(r,g,b,a);
						// cout << "- emissao: " << r << " " << g << " " << b << " " << a << endl;
					} else if(propriedade->ValueTStr() == "ambient") {
						propriedade->QueryFloatAttribute("r",&r);
						propriedade->QueryFloatAttribute("g",&g);
						propriedade->QueryFloatAttribute("b",&b);
						propriedade->QueryFloatAttribute("a",&a);
						mat->setAmbiente(r,g,b,a);
						// cout << "- ambiente: " << r << " " << g << " " << b << " " << a << endl;
					} else if(propriedade->ValueTStr() == "diffuse") {
						propriedade->QueryFloatAttribute("r",&r);
						propriedade->QueryFloatAttribute("g",&g);
						propriedade->QueryFloatAttribute("b",&b);
						propriedade->QueryFloatAttribute("a",&a);
						mat->setDifusa(r,g,b,a);
						// cout << "- difusa: " << r << " " << g << " " << b << " " << a << endl;
					} else if(propriedade->ValueTStr() == "specular") {
						propriedade->QueryFloatAttribute("r",&r);
						propriedade->QueryFloatAttribute("g",&g);
						propriedade->QueryFloatAttribute("b",&b);
						propriedade->QueryFloatAttribute("a",&a);
						mat->setEspecular(r,g,b,a);
						// cout << "- especular: " << r << " " << g << " " << b << " " << a << endl;
					} else if(propriedade->ValueTStr() == "shininess") {
						propriedade->QueryFloatAttribute("value",&valor);
						mat->setBrilho(valor);
					
						// cout << "- brilho: " << valor << endl;
					} else {
						return false;
					}
					this->addMaterial(id_material,mat);
				}
			} 
			
		}
	}

	Materiais *m = new Materiais("inherit");
	m->setAmbiente(NULL,NULL,NULL,NULL);
	m->setBrilho(NULL);
	m->setDifusa(NULL,NULL,NULL,NULL);
	m->setEmissao(NULL,NULL,NULL,NULL);
	m->setEspecular(NULL,NULL,NULL,NULL);
	m->setHerda(true);
	this->addMaterial("inherit",m);
	return true;
}

// VER LENGHT_S E _T (SE SAO FLOAT'S)
bool LoadXML::loadTexturas() {
	int i = 1;
	/*
	<textures>
        <!-- Deve existir um ou mais blocos "texture" -->
        <!-- Os identificadores "id" nao podem ser repetidos -->
        <!-- s e t: factores de escala (ver notas finais) -->
        <texture id="ss" file="ss" length_s="ff" length_t="ff" />  
    </textures>
	*/
	TiXmlElement *tt = doc.RootElement()->FirstChildElement("textures");
	cout << "TEXTURAS" << endl;
	for(TiXmlElement *textura(tt->FirstChildElement()); textura != NULL; textura = textura->NextSiblingElement()) {
		
		string id_textura, fich;
		float lenght_s, lenght_t;
		int tipoTextura = 1;

		Texturas *t;

		if(textura->ValueTStr() == "texture") {
			id_textura = textura->Attribute("id");

			if(id_textura == "none") {
				tipoTextura = 0;
			} else if(id_textura == "inherit") {
				tipoTextura = 2;
			} else {
				tipoTextura = 1;
			}
			if(id_textura != "inherit" && id_textura != "none") {
			
				t = new Texturas(i,tipoTextura);

				fich = textura->Attribute("file");

				textura->QueryFloatAttribute("lenght_s",&lenght_s);
				textura->QueryFloatAttribute("lenght_t",&lenght_t);
				// cout << "tt: " << id_textura << " " << fich << " " << lenght_s << " " << lenght_t << endl;
				t->setFicheiro(fich);
				t->setLenghtS(lenght_s);
				t->setLenghtT(lenght_t);

				this->addTextura(id_textura,t);
				i++;
				// cout << "BANANAS" << endl;
			} else {
				Texturas *t = new Texturas(0,tipoTextura);
				addTextura(0,t);
			}
		} else {
			return false;
		}
	}
	Texturas *t = new Texturas(0,2);
	this->addTextura("inherit",t);
	Texturas *t_2 = new Texturas(0,0);
	this->addTextura("none",t_2);
	return true;
}

bool LoadXML::loadTransformacoes() {
	cout << "TRANSFORMACOES" << endl;
	TiXmlElement * transtrans = doc.RootElement()->FirstChildElement("transformations");

	for(TiXmlElement * transformacao(transtrans->FirstChildElement()); transformacao != NULL; transformacao = transformacao->NextSiblingElement()) {

		if(transformacao->ValueTStr() == "transformation") {
			string id_transformacao = transformacao->Attribute("id");
			vector<Transformacoes*> vecTemp;
			vecTemp.clear();
			// cout << "id_transf: " << id_transformacao << endl;
			for(TiXmlElement * tipo_transf(transformacao->FirstChildElement()); tipo_transf != NULL; tipo_transf = tipo_transf->NextSiblingElement()) {
				float xT,yT,zT,xE,yE,zE,angulo;
				string axis;

				if(tipo_transf->ValueTStr() == "translate") {

					tipo_transf->QueryFloatAttribute("x",&xT);
					tipo_transf->QueryFloatAttribute("y",&yT);
					tipo_transf->QueryFloatAttribute("z",&zT);
					
					Translacao *t = new Translacao(xT,yT,zT);
					vecTemp.push_back(t);
					// cout << "- translacao: " << xT << " " << yT << " " << zT << endl;
				} else if(tipo_transf->ValueTStr() == "rotate") {

					axis = tipo_transf->Attribute("axis");
					tipo_transf->QueryFloatAttribute("angle",&angulo);

					Rotacao *r = new Rotacao(axis, angulo);
					vecTemp.push_back(r);
					
					// cout << "- rotacao: " << axis << " " << angulo << endl;
				} else if(tipo_transf->ValueTStr() == "scale") {

					tipo_transf->QueryFloatAttribute("x",&xE);
					tipo_transf->QueryFloatAttribute("y",&yE);
					tipo_transf->QueryFloatAttribute("z",&zE);

					Escalamento *e = new Escalamento(xE,yE,zE);
					vecTemp.push_back(e);
					
					// cout << "- escalamento: " << xE << " " << yE << " " << zE << endl;
				} else {
					return false;
				}


			}
			Transformacoes *trans = new Transformacoes(vecTemp);
			this->addTransformacao(id_transformacao, trans);
		}

	}
	return true;
}

bool LoadXML::loadIluminacao() {

	cout << "ILUMINACAO" << endl;
	TiXmlElement * ii = doc.RootElement()->FirstChildElement("illumination");
	int doublesided, local;
	Iluminacao *i = new Iluminacao();

	ii->QueryIntAttribute("doublesided", &doublesided);
	ii->QueryIntAttribute("local", &local);
	i->setDoublesided(doublesided);
	i->setLocal(local);
	// cout << doublesided << " " << local << endl;
	for(TiXmlElement * iluminacao(ii->FirstChildElement()); iluminacao != NULL; iluminacao = iluminacao->NextSiblingElement() ) {
		float rI,gI,bI,aI,rB,gB,bB,aB;

		if(iluminacao->ValueTStr() == "ambient") {
			iluminacao->QueryFloatAttribute("r", &rI);
			iluminacao->QueryFloatAttribute("g", &gI);
			iluminacao->QueryFloatAttribute("b", &bI);
			iluminacao->QueryFloatAttribute("a", &aI);

			i->setAmbiente(rI,gI,bI,aI);
			// cout << "Ambiente: " << rI << " " << gI << " " << bI << " " << aI << endl;
		} else if(iluminacao->ValueTStr() == "background") {
			iluminacao->QueryFloatAttribute("r", &rB);
			iluminacao->QueryFloatAttribute("g", &gB);
			iluminacao->QueryFloatAttribute("b", &bB);
			iluminacao->QueryFloatAttribute("a", &aB);

			i->setBackground(rB,gB,bB,aB);
			// cout << "background: " << rB << " " << gB << " " << bB << " " << aB << endl;
		} else {
			return false;
		}

	}
	this->defineIluminacao(i);
	i->aplica();
	return true;
}


bool LoadXML::loadLuzes() {   //mandar a psodente eu e ela estamos a trabalhar n mesmo ficheiro

	TiXmlElement *ll = doc.RootElement()->FirstChildElement("lights");
	cout << "LUZES" << endl;

	for(TiXmlElement *luz(ll->FirstChildElement()); luz != NULL; luz = luz->NextSiblingElement()) {
		
		if(luz->ValueTStr() == "omni"){
			
			Omni *luzinha = new Omni();
			string id_omni = luz->Attribute("id");
			int enabled_omni = luz->QueryIntAttribute("enabled",&enabled_omni);

			luzinha->setEnabled(enabled_omni);
			for(TiXmlElement* propriedade(luz->FirstChildElement()); propriedade != NULL; propriedade = propriedade->NextSiblingElement()) {
				
				// cout << "luz: " << id_omni << endl;
				float x,y,z,w,r,g,b,a;
			
				if(propriedade->ValueTStr() == "location") {
					// cout << "location: " << endl;
					propriedade->QueryFloatAttribute("x",&x);
					propriedade->QueryFloatAttribute("y",&y);
					propriedade->QueryFloatAttribute("z",&z);
					propriedade->QueryFloatAttribute("w",&w);
					luzinha->setLocalizacao(x,y,z,w);
					// cout << "-location: " << x << ' ' <<  y << ' ' << z << ' ' << w << endl;
				}

				else if(propriedade->ValueTStr() == "ambient") {
					// cout << "ambient: " << endl;
					propriedade->QueryFloatAttribute("r",&r);
					propriedade->QueryFloatAttribute("g",&g);
					propriedade->QueryFloatAttribute("b",&b);
					propriedade->QueryFloatAttribute("a",&a);
					luzinha->setAmbiente(r,g,b,a);
					// cout << "-ambient: " << r << ' ' <<  g << ' ' << b << ' ' << a << endl;
				}

				else if(propriedade->ValueTStr() == "diffuse") {
					// cout << "diffuse: " << endl;
					propriedade->QueryFloatAttribute("r",&r);
					propriedade->QueryFloatAttribute("g",&g);
					propriedade->QueryFloatAttribute("b",&b);
					propriedade->QueryFloatAttribute("a",&a);
					luzinha->setDifusa(r,g,b,a);
					// cout << "-diffuse: " << r << ' ' <<  g << ' ' << b << ' ' << a << endl;
				}

				else if(propriedade->ValueTStr() == "specular") {
					// cout << "specular: " << endl;
					propriedade->QueryFloatAttribute("r",&r);
					propriedade->QueryFloatAttribute("g",&g);
					propriedade->QueryFloatAttribute("b",&b);
					propriedade->QueryFloatAttribute("a",&a);
					luzinha->setEspecular(r,g,b,a);
					// cout << "-specular: " << r << ' ' <<  g << ' ' << b << ' ' << a << endl;
				}

				else {
					return false;
				}

				addLuz(id_omni, luzinha);
			
			}
		}

		if(luz->ValueTStr() == "spot"){
			Spot *luzinha = new Spot();
			string id_spot = luz->Attribute("id");
			int enabled_spot = luz->QueryIntAttribute("enabled",&enabled_spot);
			float angle_spot = luz->QueryFloatAttribute("angle",&angle_spot);
			float exponent_spot = luz->QueryFloatAttribute("exponent",&exponent_spot);

			luzinha->setEnabled(enabled_spot);
			luzinha->setAngulo(angle_spot);
			luzinha->setExponent(exponent_spot);

			for(TiXmlElement* propriedade(luz->FirstChildElement()); propriedade != NULL; propriedade = propriedade->NextSiblingElement()) {

				// cout << "luz: " << id_spot << endl;
				float x,y,z,r,g,b,a;

				if(propriedade->ValueTStr() == "location") {
					// cout << "location: " << endl;
					propriedade->QueryFloatAttribute("x",&x);
					propriedade->QueryFloatAttribute("y",&y);
					propriedade->QueryFloatAttribute("z",&z);
					luzinha->setLocalizacao(x,y,z);
					// cout << "-location: " << x << ' ' << y << ' ' << z << endl;
				}

				else if(propriedade->ValueTStr() == "target") {
					// cout << "target: " << endl;
					propriedade->QueryFloatAttribute("x",&x);
					propriedade->QueryFloatAttribute("y",&y);
					propriedade->QueryFloatAttribute("z",&z);
					luzinha->setTarget(x,y,z);
					// cout << "-target: " << x << ' ' << y << ' ' << z << endl;
				}

				else if(propriedade->ValueTStr() == "ambient") {
					// cout << "ambient: " << endl;
					propriedade->QueryFloatAttribute("r",&r);
					propriedade->QueryFloatAttribute("g",&g);
					propriedade->QueryFloatAttribute("b",&b);
					propriedade->QueryFloatAttribute("a",&a);
					luzinha->setAmbiente(r,g,b,a);
					// cout << "-ambient: " << r << ' ' << g << ' ' << b << ' ' << a << endl;
				}

				else if(propriedade->ValueTStr() == "diffuse") {
					// cout << "diffuse: " << endl;
					propriedade->QueryFloatAttribute("r",&r);
					propriedade->QueryFloatAttribute("g",&g);
					propriedade->QueryFloatAttribute("b",&b);
					propriedade->QueryFloatAttribute("a",&a);
					luzinha->setDifusa(r,g,b,a);
					// cout << "-diffuse: " << r << ' ' << g << ' ' << b << ' ' << a << endl;
				}

				else if(propriedade->ValueTStr() == "specular") {
					// cout << "specular: " << endl;
					propriedade->QueryFloatAttribute("r",&r);
					propriedade->QueryFloatAttribute("g",&g);
					propriedade->QueryFloatAttribute("b",&b);
					propriedade->QueryFloatAttribute("a",&a);
					luzinha->setEspecular(r,g,b,a);
					// cout << "-specular: " << r << ' ' << g << ' ' << b << ' ' << a << endl;
				}

				else {

					return false;
				}

				addLuz(id_spot, luzinha);

			}
		}
	}
		
	return true;
}

void LoadXML::addLuz(string id, Luzes *l){
	this->luzes.insert(pair<string,Luzes*>(id,l));
}


bool LoadXML::loadVistas() {
	/*
	<views default="vista" >
        <!-- tem de existir, pelo menos, uma vista das -->
        <!-- seguintes (perspective ou ortho) -->
        <perspective id="vista1" near="10.0" far="100.0" angle="20.0">
            <from x="ff" y="ff" z="ff" />
            <to x="ff" y="ff" z="ff" />
        </perspective>
        <ortho id="vista2" near="ff" far="ff" left="ff" right="ff" top="ff" bottom="ff" />
    </views>
	*/
	cout << "VISTAS" << endl;
	TiXmlElement * vv = doc.RootElement()->FirstChildElement("views");
	string default = vv->Attribute("default");
	//  cout << "DEFAULT: " << default << endl;

	for(TiXmlElement * vista(vv->FirstChildElement()); vista != NULL; vista = vista->NextSiblingElement()) {

		if(vista->ValueTStr() == "perspective") {
			string id_perspective;
			float perto, longe, angulo;

			Perspectiva *p = new Perspectiva();
			id_perspective = vista->Attribute("id");
			vista->QueryFloatAttribute("near",&perto);
			vista->QueryFloatAttribute("far",&longe);
			vista->QueryFloatAttribute("angle",&angulo);

			p->setPerto(perto);
			p->setLonge(longe);
			p->setAngulo(angulo);
			
			// cout << "Perspectiva: " << id_perspective << endl;
			// cout << perto << " " <<  longe << " " << angulo << endl;

			float xF,yF,zF,xT,yT,zT;
			for(TiXmlElement * propriedades(vista->FirstChildElement()); propriedades != NULL; propriedades = propriedades->NextSiblingElement() ) {

				if(propriedades->ValueTStr() == "from") {
					
					propriedades->QueryFloatAttribute("x",&xF);
					propriedades->QueryFloatAttribute("y",&yF);
					propriedades->QueryFloatAttribute("z",&zF);

					p->setFrom(xF,yF,zF);
					// cout << "FROM: " << xF << ',' << yF << ',' << zF << endl;
				} else if(propriedades->ValueTStr() == "to") {
					
					propriedades->QueryFloatAttribute("x",&xT);
					propriedades->QueryFloatAttribute("y",&yT);
					propriedades->QueryFloatAttribute("z",&zT);
					
					p->setTo(xT,yT,zT);
					// cout << "TO: " << xT << ',' << yT << ',' << zT << endl;

				} else {
					return false;
				}
			}
			this->addVista(id_perspective,p);

		} else if(vista->ValueTStr() == "ortho") {
			
			string id_ortho;
			float perto, longe, esq, dir, topo, fundo;

			Ortho *o = new Ortho();
			id_ortho = vista->Attribute("id");
			vista->QueryFloatAttribute("near",&perto);
			vista->QueryFloatAttribute("far",&longe);
			vista->QueryFloatAttribute("left",&esq);
			vista->QueryFloatAttribute("right",&dir);
			vista->QueryFloatAttribute("top",&topo);
			vista->QueryFloatAttribute("bottom",&fundo);

			o->setPerto(perto);
			o->setLonge(longe);
			o->setEsquerda(esq);
			o->setDireita(dir);
			o->setTopo(topo);
			o->setFundo(fundo);

			// cout << "Ortho: " << id_ortho << endl;
			// cout << perto << " " <<  longe << " " << esq << " " << dir << " " << topo << " " << fundo << endl;

			this->addVista(id_ortho,o);

		} else {
			return false;
		}
	}
	return true;
}

bool LoadXML::loadPrimitivas() {

	bool material_existe = true;
	Texturas *t;
	Materiais *m;

	TiXmlElement *pp = doc.RootElement()->FirstChildElement("primitives");
	
	cout << "PRIMITIVAS" << endl;

	for(TiXmlElement *primitiva(pp->FirstChildElement()); primitiva != NULL; primitiva = primitiva->NextSiblingElement()) {

		if(primitiva->ValueTStr() == "primitive"){

			string id_primitiva = primitiva->Attribute("id");
			// cout << "Id: " << id_primitiva << endl;

			for(TiXmlElement* tipo(primitiva->FirstChildElement()); tipo != NULL; tipo = tipo->NextSiblingElement()) {

				string id;

				
				if(tipo->ValueTStr() == "material"){
					string id_material = tipo->Attribute("id");

					m = encontra_M(id_material);
					if(m == NULL) {
						cout << "ERRO_Material nao existe" << endl;
						material_existe = false;
						return false;
					}

				}

				else if(tipo->ValueTStr() == "texture"){
					string id_textura = tipo->Attribute("id");
					t = encontra_T(id_textura);
					if(t == NULL) {
						cout << "ERRO_Textura nao existe" << endl;
						return false;
					}
					// cout << "-texture: " << id_textura << endl; 

				}

			}

			for(TiXmlElement* tipo(primitiva->FirstChildElement()); tipo != NULL; tipo = tipo->NextSiblingElement()) {

				float x1, y1, z1, x2, y2, z2, x3, y3, z3, base, top, height, radius, inner, outer, loops;
				int slices, stacks;

				if(tipo->ValueTStr() == "rectangle"){
					// cout << "Rectangle: " << endl;
					tipo->QueryFloatAttribute("x1",&x1);
					tipo->QueryFloatAttribute("y1",&y1);
					tipo->QueryFloatAttribute("x2",&x2);
					tipo->QueryFloatAttribute("y2",&y2);

					Rectangulo *R = new Rectangulo(m, t, x1, y1, x2, y2);
					addRectangulo(id_primitiva,R);
					// cout << "-rectangle: " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl; 

				}

				else if(tipo->ValueTStr() == "triangle"){
					// cout << "Triangle: " << endl;
					tipo->QueryFloatAttribute("x1",&x1);
					tipo->QueryFloatAttribute("y1",&y1);
					tipo->QueryFloatAttribute("z1",&z1);
					tipo->QueryFloatAttribute("x2",&x2);
					tipo->QueryFloatAttribute("y2",&y2);
					tipo->QueryFloatAttribute("z2",&z2);
					tipo->QueryFloatAttribute("x3",&x3);
					tipo->QueryFloatAttribute("y3",&y3);
					tipo->QueryFloatAttribute("z3",&z3);

					Triangulo *T = new Triangulo(m, t, x1, y1, z1, x2, y2, z2, x3, y3, z3);
					addTriangulo(id_primitiva,T);
					// cout << "-triangle: " << x1 << ' ' << y1 << ' ' << z1 << ' ' << x2 << ' ' << y2 << ' ' << z2 << ' ' << x3 << ' ' << y3 << ' ' << z3 << endl; 

				}

				else if(tipo->ValueTStr() == "cylinder"){
					// cout << "Cylinder: " << endl;
					tipo->QueryFloatAttribute("base",&base);
					tipo->QueryFloatAttribute("top",&top);
					tipo->QueryFloatAttribute("height",&height);
					tipo->QueryIntAttribute("slices",&slices);
					tipo->QueryIntAttribute("stacks",&stacks);

					Cilindro *C = new Cilindro(m, t, base, top, height, slices, stacks);
					addCilindro(id_primitiva,C);
					// cout << "-cylinder: " << base << ' ' << top << ' ' << height << ' ' << slices << ' ' << stacks << endl; 

				}

				else if(tipo->ValueTStr() == "sphere"){
					// cout << "Sphere: " << endl;
					tipo->QueryFloatAttribute("radius",&radius);
					tipo->QueryIntAttribute("slices",&slices);
					tipo->QueryIntAttribute("stacks",&stacks);

					Esfera *E = new Esfera(m, t, radius, slices, stacks);
					addEsfera(id_primitiva,E);
					// cout << "-sphere: " << radius << ' ' << slices << ' ' << stacks << endl; 

				}

				else if(tipo->ValueTStr() == "torus"){
					// cout << "Torus: " << endl;
					tipo->QueryFloatAttribute("inner",&inner);
					tipo->QueryFloatAttribute("outer",&outer);
					tipo->QueryIntAttribute("slices",&slices);
					tipo->QueryFloatAttribute("loops",&loops);

					Torus *To = new Torus(m, t, inner, outer, slices, loops);
					addTorus(id_primitiva,To);
					// cout << "-torus: " << inner << ' ' << outer << ' ' << slices << ' ' << loops << endl; 

				}
			} 
		}
	}
}

bool LoadXML::loadComponentes() {

	cout << "LOAD COMPONENTES" << endl;

	TiXmlElement *cc = doc.RootElement()->FirstChildElement("components");

	for(TiXmlElement * componente(cc->FirstChildElement()); componente != NULL; componente = componente->NextSiblingElement()) {
		
		Componente *comp = new Componente();
		
		cout << "tamanhinho " << comp->getMateriais().size() << endl;
		vector<Materiais*> matt;
		matt.clear();
		comp->setMateriais(matt);

		cout << "tamanhinho_2 " << comp->getMateriais().size() << endl;
		string id_componente = componente->Attribute("id");
		comp->setId(id_componente);
		Texturas *t;
		Materiais *m;
		Primitiva *p;
		Componente *c;
		string id_textura, id_material, key, id_primitiva;
		// cout << " id: " << id_componente << endl;
		vector<Transformacoes*> vecTemp;
		vecTemp.clear();

		cout << "UM COMPONENTE " << id_componente << endl;

		for(TiXmlElement * tipo(componente->FirstChildElement()); tipo != NULL; tipo = tipo->NextSiblingElement()) {
	
			if(tipo->ValueTStr() == "texture"){
				// cout << "Entra em textura: " << endl;
				id_textura = tipo->Attribute("id");

				t = encontra_T(id_textura);

				if(t == NULL) {
					cout << "ERRO_Textura nao existe" << endl;
					return false;
				}
				// cout << "-> textura id: " << id_textura << endl;
				comp->setTextura(t);

			} else if(tipo->ValueTStr() == "transformation"){
				Transformacoes *trans = new Transformacoes();
				// cout << "Entra em Transformacoes: " << endl;
				TiXmlElement * filho3;
				if(( filho3=tipo->FirstChildElement()) == NULL) {
		
					Translacao *T = new Translacao(1,1,1);
					comp->setTransformcao(T);
					vecTemp.push_back(T);


				} else {
					for(TiXmlElement * filho(tipo->FirstChildElement()); filho != NULL; filho = filho->NextSiblingElement()){
					

						if(filho->ValueTStr() == "transformationref") {
						
							string id_transf = filho->Attribute("id");
							// cout << "Id: " << id_transf << endl;
							trans = encontra_Tr(id_transf);

							if(trans == NULL) {
								cout << "ERRO_Transformacao nao existe" << endl;
								return false;
							}

							// cout << "Transformation_ref: " /*<< id_transf */ << endl;
							comp->setTransformcao(trans);
							// cout << " id: " << id_transf << endl;
						}

						else if(filho->ValueTStr() == "translate" || filho->ValueTStr() == "rotate" || filho->ValueTStr() == "scale"){

							// cout << " transformation normal" << endl;
							if(filho->ValueTStr() == "translate"){
								float xT, yT, zT;

								filho->QueryFloatAttribute("x",&xT);
								filho->QueryFloatAttribute("y",&yT);
								filho->QueryFloatAttribute("z",&zT);

								Translacao *t = new Translacao(xT,yT,zT);
								comp->setTransformcao(t);
								vecTemp.push_back(t);
								// cout << "Translacao: " /*<< xT << " " << yT << " " << zT */ << endl;

							} else if(filho->ValueTStr() == "rotate") {

								float angulo;
								string axis;
								axis = filho->Attribute("axis");
								filho->QueryFloatAttribute("angle",&angulo);

								Rotacao *r = new Rotacao(axis, angulo);
								comp->setTransformcao(r);
								vecTemp.push_back(r);
								// cout << "Rotacao: " /*<< axis << " " << angulo */ << endl;
								// cout << "- rotacao: " << axis << " " << angulo << endl;
							} else if(filho->ValueTStr() == "scale") {
								float xE, yE, zE;

								filho->QueryFloatAttribute("x",&xE);
								filho->QueryFloatAttribute("y",&yE);
								filho->QueryFloatAttribute("z",&zE);

								Escalamento *e = new Escalamento(xE,yE,zE);
								comp->setTransformcao(e);
								vecTemp.push_back(e);
								// cout << "Escalamento: " /*<< xE << " " << yE << " " << zE*/ << endl;
							}
						}
						trans = new Transformacoes(vecTemp);
					}
				}
			}

			else if(tipo->ValueTStr() == "materials"){
				// cout << "Entra em Materiais: " << endl;
				// cout << "Argumentos: " << numArg(tipo) << endl;
				if(numArg(tipo) == 0){
					// cout << "materiais normais ";
					TiXmlElement *filhinho(tipo->FirstChildElement());
					id_material = filhinho->Attribute("id");
					cout << id_material << endl;
					m = encontra_M(id_material);

					if(m == NULL){
						cout << "ERRO_Material nao existe" << endl;
						return false;
					}
					cout << "tamanho2: " << comp->getMateriais().size() << endl;
					matt.push_back(m);
					// comp->addMaterial(m);
				}
				else {
					// cout << "materiais key " << endl;
					key = tipo->Attribute("key");
					string id_material2;
					Materiais *m2;
					for(TiXmlElement * filhinho2(tipo->FirstChildElement()); filhinho2 != NULL; filhinho2 = filhinho2->NextSiblingElement()){
						id_material2 = filhinho2->Attribute("id");
						m2 = encontra_M(id_material2);

						if(m2 == NULL){
							cout << "ERRO_Material nao existe" << endl;
							return false;
						}

						cout << "tamanho2: " << comp->getMateriais().size() << endl;
						matt.push_back(m2);
						// comp->addMaterial(m2);
						// cout << "-> id: " << id_material << endl;
					}
				}
			}

			else if(tipo->ValueTStr() == "children"){
				// cout << "Entra em Children: " << endl;
				for(TiXmlElement * filhote(tipo->FirstChildElement()); filhote != NULL; filhote = filhote->NextSiblingElement()){
					
					if(filhote->ValueTStr() == "primitiveref"){
						// cout << "primitivas ref " << endl;
						id_primitiva = filhote->Attribute("id");

						p = encontra_P(id_primitiva);

						if(p == NULL){
							// cout << "ERRO_Primitiva nao existe" << endl;
							return false;
						}

						comp->addPrimitiva(p);
						// cout << "-> id: " << id_primitiva << endl;
					} 
					else if(filhote->ValueTStr() == "componentref"){
						string id_componenteref;
						// cout << "componente ref " << endl;
						id_componenteref = filhote->Attribute("id");
						
						// cout << "id -- " << id_componenteref << endl;
						c = encontra_C(id_componenteref);
						// cout << "id -- " << id_componenteref << endl;
						if(c == NULL){
							cout << "ERRO_Componente nao existe" << endl;
							return false;
						}
						comp->addComponente(c);
						// cout << "-> id: " << id_componente << endl;
					} else {
						cout << "saiste aqui e nao devias pk? " << endl;
						return false;
					}
				}

			}
		}
		comp->setMateriais(matt);
		this->addComponente(id_componente,comp);
		// cout << "devia passar aqui!" << endl;
		// cout << "id'': " << id_componente << endl;
		matt.clear();
		// this->addComponente(id_componente,comp);
	}
}

void LoadXML::aplicaLuzes() {
	
	map<string, Luzes*>::iterator it = luzes.begin();
	for (; it != luzes.end(); it++){
		it->second->aplica();
	}

}
void LoadXML::addComponente(string id, Componente *comp) {
	this->componentes.insert(pair<string, Componente*>(id,comp));
}

void LoadXML::addRectangulo(string id, Rectangulo *r){
	this->primitivas.insert(pair<string,Primitiva*>(id,r));
}

void LoadXML::addTriangulo(string id, Triangulo *t){
	this->primitivas.insert(pair<string,Primitiva*>(id,t));
}

void LoadXML::addCilindro(string id, Cilindro *c){
	this->primitivas.insert(pair<string,Primitiva*>(id,c));
}

void LoadXML::addEsfera(string id, Esfera *e){
	this->primitivas.insert(pair<string,Primitiva*>(id,e));
}

void LoadXML::addTorus(string id, Torus *to){
	this->primitivas.insert(pair<string,Primitiva*>(id,to));
}

void LoadXML::addTextura(string id, Texturas *t) {
	this->texturas.insert(pair<string,Texturas*>(id,t));
}

void LoadXML::addMaterial(string id, Materiais *m) {
	this->materiais.insert(pair<string,Materiais*>(id,m));
}

void LoadXML::addVista(string id, View *v) {
	this->vistas.insert(pair<string,View*>(id,v));
}

void LoadXML::addTransformacao(string id, Transformacoes *trans) {
	this->transformacoes.insert(pair<string,Transformacoes*>(id,trans));
}

void LoadXML::defineIluminacao(Iluminacao *i) {
	this->iluminacao = i;
}